package com.isoft.c2team3service2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.isoft.c2team3service2.dto.PostDTO;
import com.isoft.c2team3service2.entity.*;
import com.isoft.c2team3service2.mapper.*;
import com.isoft.c2team3service2.service.*;
import com.isoft.c2team3service2.util.UserHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.isoft.c2team3service2.util.RedisConstants.ARTIST_RELATED_POST_DETAIL;
/**
 * 帖子服务实现
 */
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements PostService {
    private static final Logger log = LoggerFactory.getLogger(PostServiceImpl.class);

    // 新增依赖注入
    @Autowired
    private UserPaidPostService userPaidPostService;

    @Autowired
    private SensitiveWordService sensitiveWordService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private CommentService commentService; // 新增评论服务注入

    @Autowired
    private FileService fileService; // 新增文件服务注入

    @Autowired
    private PostArtistTagService postArtistTagService; // 添加艺人标签服务注入

    @Autowired
    private ArtistMapper artistMapper; // 添加艺人Mapper注入

    @Autowired
    private PostArtistTagMapper postArtistTagMapper;

    @Autowired
    private PostMapper postMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private HeadMapper headMapper;

    @Autowired
    private UserLikeMapper userLikeMapper;

    @Override
    @Transactional
    public boolean createPost(MultipartFile file, String title, String content, Integer isPaid, Integer isPrivate, BigDecimal price) {
        // 创建Post对象并设置基本属性
        Post post = new Post();
        post.setTitle(title);
        post.setContent(content);
        // 1. 敏感词过滤
        String filteredContent = sensitiveWordService.filterText(post.getContent());
        post.setFilteredContent(filteredContent);
        post.setIsPrivate(isPrivate);
        post.setIsPaid(isPaid);
        post.setPrice(price);       // 2. 获取当前用户
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            log.error("创建帖子失败：用户未登录");
            return false;
        }

        // 3. 校验付费和私密状态冲突（不能同时为1）
        if (isPaid == 1 && isPrivate == 1) {
            log.error("创建帖子失败：帖子不能同时设置为付费（isPaid=1）和私密（isPrivate=1）");
            return false;
        }

        // 4. 校验付费帖子的价格
        if (isPaid == 1) {
            if (price == null || price.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("创建帖子失败：付费帖子价格必须大于0，当前价格：{}", price);
                return false;
            }
            post.setIsPaid(isPaid);
            post.setPrice(price);
        } else {
            // 非付费帖子，价格强制设为null
            post.setPrice(null);
            post.setIsPaid(0);
        }

        // 设置默认值和用户信息
        post.setViewCount(0);
        post.setLikeCount(0);
        post.setCommentCount(0);
        post.setStatus(1); // 默认为发布状态
        post.setCreateTime(LocalDateTime.now());

        if (file != null) {
            post.setPhotoUrl(fileService.upPostPhoto(file,"postPicture"));
        }

        post.setUpdateTime(LocalDateTime.now());
        post.setUserId(user.getId());
        post.setNickName(user.getNickName());
        // 5. 保存帖子并返回结果
        boolean saveSuccess = save(post);
        log.info("用户{}创建帖子结果：{}，帖子信息：isPaid={}, isPrivate={}, price={}",
                user.getId(), saveSuccess, post.getIsPaid(), post.getIsPrivate(), post.getPrice());
        return saveSuccess;
    }
    @Override
    public Post findById(Integer id) {
        Post post = getById(id);
        if (post == null) {
            return null;
        }

        UserDTO currentUser = UserHolder.getUser();

        // 1. 原有私密帖子权限校验（保留）
        if (post.getIsPrivate() == 1) {
            if (currentUser == null || !post.getUserId().equals(currentUser.getId())) {
                return null; // 非作者无法查看私密帖子
            }
        }

        // 2. 新增付费帖子权限校验
        if (post.getIsPaid() == 1) { // 若是付费帖子
            // 未登录用户：返回登录提示
            if (currentUser == null) {
                Post hintPost = new Post();
                hintPost.setId(post.getId());
                hintPost.setTitle(post.getTitle());
                hintPost.setContent("请先登录后购买查看完整内容");
                hintPost.setIsPaid(1); // 标记为付费帖子
                hintPost.setPrice(post.getPrice());
                return hintPost;
            }

            // 已登录用户：检查是否为作者或已购买
            boolean isAuthor = post.getUserId().equals(currentUser.getId());
            boolean hasPaid = userPaidPostService.hasPaid(currentUser.getId(), id);

            if (!isAuthor && !hasPaid) {
                // 非作者且未购买：返回购买提示
                Post hintPost = new Post();
                hintPost.setId(post.getId());
                hintPost.setTitle(post.getTitle());
                hintPost.setContent("该内容为付费内容，购买后可查看完整内容");
                hintPost.setIsPaid(1);
                hintPost.setPrice(post.getPrice());
                return hintPost;
            }
        }

        // 3. 权限通过：返回完整帖子并增加浏览量
        increaseViewCount(id);
        return post;
    }
    @Override
    public List<PostDTO> findByUserId(Integer userId) {
        return postMapper.findByUserId(userId);
    }

    @Override
    public List<PostDTO> findHotPosts(int num) {
        return postMapper.findHotPosts(num);
    }

    @Override
    public List<PostDTO> findLatestPosts(int num) {
        return postMapper.findLatestPosts(num);
    }

    @Override
    @Transactional
    public boolean updatePost(Post post ,MultipartFile  file) {
        Post p = new Post();

        BeanUtil.copyProperties(post, p);

        // 敏感词过滤
        String filteredContent = sensitiveWordService.filterText(post.getContent());
        p.setFilteredContent(filteredContent);
        p.setUpdateTime(LocalDateTime.now());

        if (file != null) {
            p.setPhotoUrl(fileService.upPostPhoto(file,"postPicture"));
        }

        // 检查是否为作者本人更新
        Post originalPost = getById(post.getId());
        if (originalPost == null || !originalPost.getUserId().equals(UserHolder.getUser().getId())) {
            return false;
        }

        return updateById(p);
    }

    @Override
    @Transactional
    public boolean deletePost(Integer id, Integer userId) {
        // 检查帖子是否存在
        Post post = getById(id);
        if (post == null) {
            return false;
        }

        // 检查是否为作者本人删除
        if (!post.getUserId().equals(userId)) {
            return false;
        }

        // 物理删除帖子（彻底从数据库删除）
        boolean success = removeById(id);

        if (success) {
            // 新增：删除帖子关联的艺人标签
            postArtistTagService.deleteTagsByPostId(id);
            log.info("删除帖子{}时，同步删除关联的艺人标签", id);
            // 物理删除该帖子的所有评论
            commentService.remove(new LambdaQueryWrapper<Comment>()
                    .eq(Comment::getPostId, id));
        }
        return success;
    }

    @Override
    public boolean increaseViewCount(Integer postId) {
        // 调用mapper的updateViewCount方法，返回影响行数（1表示成功，0表示失败）
        int rows = baseMapper.updateViewCount(postId);
        return rows > 0; // 影响行数>0说明更新成功
    }

    @Override
    public boolean likePost(Integer postId) {
        boolean update = lambdaUpdate()
                .eq(Post::getId, postId)
                .setSql("like_count = like_count + " + 1)
                .update();
        UserLike userLike = new UserLike();
        userLike.setUserId(UserHolder.getUser().getId());
        userLike.setPostId(postId);
        int insert = userLikeMapper.insert(userLike);

        if (insert > 0 && update) {
            return true;
        }
        return false;
    }

    @Override
    public boolean unlikePost(Integer postId) {
        // 使用 MyBatis-Plus 的 LambdaUpdateWrapper 替代 XML
        boolean update = lambdaUpdate()
                .eq(Post::getId, postId)
                .setSql("like_count = like_count - " + 1)
                .update();
        int userId = userLikeMapper.delete(new QueryWrapper<UserLike>().eq("user_id", UserHolder.getUser().getId()));

        if (userId > 0 && update) {
            return true;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean setPostPrivate(Integer postId, Integer userId, Integer isPrivate) {
        // 1. 查询帖子是否存在
        Post post = getById(postId);
        if (post == null) {
            return false;
        }

        // 2. 验证是否为作者本人操作
        if (!post.getUserId().equals(userId)) {
            return false;
        }

        // 3. 验证状态是否需要变更
        if (Integer.valueOf(1).equals(post.getIsPrivate())) {
            return true; // 状态未变更，视为操作成功
        }

        // 4. 更新私密状态
        post.setIsPrivate(isPrivate);
        post.setUpdateTime(LocalDateTime.now());
        return updateById(post);
    }

    /**
     * 查询用户的私密帖子：仅查询状态为已发布、且标记为私密的帖子
     */
    @Override
    public List<Post> findPrivatePostsByUserId(Integer userId) {
        return lambdaQuery()
                .eq(Post::getUserId, userId) // 匹配当前用户ID
                .eq(Post::getStatus, 1) // 仅查询已发布的帖子（排除草稿、删除状态）
                .eq(Post::getIsPrivate, 1) // 仅查询私密帖子（isPrivate=1）
                .orderByDesc(Post::getCreateTime) // 按创建时间倒序（最新的在前）
                .list(); // 执行查询并返回列表
    }

    @Override
    @Transactional
    public boolean setPostPaid(Integer postId, Integer userId, boolean isPaid, BigDecimal price) {
        Post post = getById(postId);
        if (post == null || !post.getUserId().equals(userId)) {
            return false;
        }

        // 禁止同时设置为私密和付费
        if (isPaid && post.getIsPrivate() == 1) {
            log.warn("帖子{}不能同时设置为私密和付费");
            return false;
        }

        post.setIsPaid(isPaid ? 1 : 0);
        post.setPrice(isPaid ? price : null);
        return updateById(post);
    }


    /**
     * 查询公开的付费帖子（排除私密帖）
     */
    @Override
    public List<Post> findPublicPaidPosts(int limit) {
        return lambdaQuery()
                .eq(Post::getIsPaid, 1) // 仅查询付费帖子
                .eq(Post::getIsPrivate, 0) // 排除私密帖（只返回公开帖）
                .eq(Post::getStatus, 1) // 仅查询已发布的帖子（排除草稿、删除状态）
                .orderByDesc(Post::getCreateTime) // 按创建时间倒序（最新的付费帖在前）
                .last("LIMIT " + limit) // 限制返回数量
                .list();
    }

    @Override
    public List<Post> findPublicPostsByArtistId(Integer artistId, int limit) {
        if (artistId == null) {
            return List.of();
        }
        // 1. 查询关联的帖子ID
        List<Integer> postIds = postArtistTagMapper.selectPostIdsByArtistId(artistId);
        if (postIds.isEmpty()) {
            log.info("未查询到提及艺人ID:{}的帖子关联记录", artistId);
            return List.of();
        }
        // 2. 修复逻辑：仅过滤“已发布、非私密”，不排除付费帖子
        List<Post> posts = lambdaQuery()
                .in(Post::getId, postIds)
                .eq(Post::getStatus, 1) // 已发布
                .eq(Post::getIsPrivate, 0) // 公开（非私密）
                // 移除 eq(Post::getIsPaid, 0)，允许公开付费帖子被查询
                .orderByDesc(Post::getCreateTime)
                .last("LIMIT " + limit)
                .list();

        log.info("查询到提及艺人ID:{}的公开帖子{}条", artistId, posts.size());
        return posts;
    }

    /**
     * 新增：创建帖子并关联艺人标签（提及艺人）
     */
    @Override
    @Transactional
    public boolean createPostWithArtistTags(MultipartFile file, String title, String content,
                                            Integer isPaid, Integer isPrivate, BigDecimal price,
                                            String artistNames) {
        // 1. 先执行原有创建帖子逻辑（复用代码，生成基础帖子数据）
        boolean postSaved = createPost(file, title, content, isPaid, isPrivate, price);
        if (!postSaved) {
            log.error("创建帖子失败，无法关联艺人标签");
            return false;
        }

        // 2. 新增：解析艺人名称为「有效名称列表」（去重、去空，用于赋值给artistName）
        List<String> validArtistNames = parseArtistNamesToNames(artistNames);
        // 3. 原有逻辑：解析艺人名称为「艺人ID列表」（用于关联中间表）
        List<Integer> artistIds = parseArtistNamesToIds(artistNames);

        // 4. 查找刚创建的帖子（通过当前用户+创建时间倒序，确保获取最新帖子）
        UserDTO user = UserHolder.getUser();
        Post latestPost = lambdaQuery()
                .eq(Post::getUserId, user.getId())
                .orderByDesc(Post::getCreateTime)
                .last("LIMIT 1")
                .one();
        if (latestPost == null) {
            log.error("未找到刚创建的帖子，无法设置artistName和关联标签");
            return true; // 帖子已创建，非核心逻辑失败不回滚
        }

        // 5. 核心新增：设置Post的artistName字段（关键步骤！）
        if (!validArtistNames.isEmpty()) {
            // 方案1：单艺人关联（取第一个有效艺人名称，适合“一个帖子关联一个主要艺人”场景）
            String targetArtistName = validArtistNames.get(0);
            // 方案2：多艺人关联（用逗号拼接，适合“一个帖子提及多个艺人”场景，需确保前端能正确解析）
            // String targetArtistName = String.join(",", validArtistNames);

            latestPost.setArtistName(targetArtistName); // 赋值艺人名称
            updateById(latestPost); // 保存到数据库（关键！否则不会更新到表中）
            log.info("帖子{}已设置artistName：{}", latestPost.getId(), targetArtistName);
        }

        // 6. 原有逻辑：关联艺人标签中间表（post_artist_tag）
        if (!artistIds.isEmpty()) {
            postArtistTagService.addArtistTagsToPost(latestPost.getId(), artistIds);
            log.info("帖子{}成功关联艺人标签，艺人ID列表：{}", latestPost.getId(), artistIds);
        } else {
            log.info("帖子未提及有效艺人，无需关联标签");
        }

        return true;
    }

    // 新增工具方法：解析艺人名称字符串为「有效名称列表」（去重、去空）
    private List<String> parseArtistNamesToNames(String artistNames) {
        if (artistNames == null || artistNames.trim().isEmpty()) {
            return List.of(); // 无艺人名称时返回空列表
        }
        // 分割（逗号分隔）→ 去空格 → 过滤空字符串 → 去重
        return Arrays.stream(artistNames.split(","))
                .map(String::trim)
                .filter(name -> !name.isEmpty())
                .distinct()
                .collect(Collectors.toList());
    }

    // 优化原有工具方法：复用parseArtistNamesToNames，确保艺人ID和名称解析逻辑一致
    private List<Integer> parseArtistNamesToIds(String artistNames) {
        // 先调用新增的工具方法获取有效名称列表（避免重复逻辑）
        List<String> validArtistNames = parseArtistNamesToNames(artistNames);
        if (validArtistNames.isEmpty()) {
            return List.of();
        }

        // 根据有效名称查询艺人ID（精确匹配，确保与artist表name一致）
        List<Artist> artists = artistMapper.selectList(
                new LambdaQueryWrapper<Artist>()
                        .in(Artist::getName, validArtistNames)
        );
        // 提取艺人ID列表
        return artists.stream()
                .map(Artist::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    public List<PostDTO> findPostsByArtistNameLike(String artistName, int limit) {
        // 1. 按艺人名称查询关联的帖子ID
        List<Integer> postIds = postArtistTagService.getPostIdsByArtistNameLike(artistName);
        if (postIds.isEmpty()) {
            log.info("未查询到提及艺人[{}]的帖子", artistName);
            return List.of();
        }

        // 2. 查询帖子详情（仅返回公开、已发布的帖子，兼容权限逻辑）
        List<PostDTO> posts = postMapper.findPosts(artistName, limit);

        posts.forEach(p -> {
            p.setUserRole(findUserRole(p.getUserId()));
            p.setPhoto(headMapper.selectHead(p.getUserId()));
        });

        try {
            String key = ARTIST_RELATED_POST_DETAIL + ":" + artistName;
            String jsonValue = objectMapper.writeValueAsString(posts);
            stringRedisTemplate.opsForValue().set(key, jsonValue);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return posts;
    }

    @Override
    public List<PostDTO> searchPosts(String content) {
        List<Post> posts = postMapper.selectList(new LambdaQueryWrapper<Post>().like(Post::getContent, content));

        if (posts.isEmpty()) {
            return null;
        }

        List<PostDTO> postDtoS = new ArrayList<>();
        posts.forEach(p -> {
            PostDTO dto = new PostDTO();
            dto.setUserRole(findUserRole(p.getUserId()));
            dto.setPhoto(headMapper.selectHead(p.getUserId()));
            BeanUtil.copyProperties(p, dto);
            postDtoS.add(dto);
        });

        return postDtoS;
    }

    @Override
    public boolean checkLikeStatus(Integer id) {
        Integer userId = UserHolder.getUser().getId();
        return userLikeMapper.isLike( userId,id);
    }

    public String findUserRole(Integer id){
        String role ;
        Integer userId ;
        if(id == null){
            return null;
        }else{
            userId = userMapper.selectUserRoleId(id);
        }
        if(userId == 1){
            role = "艺人";
        }else if(userId == 2){
            role = "会员";
        }else if(userId == 3){
            role = "普通用户";
        }else {
            role = "管理员";
        }
        return role;
    }

}